package lmh.example.exam2_3;

import android.opengl.GLSurfaceView.Renderer;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;


public class MyRenderer implements Renderer {
    FloatBuffer mVertexBuffer;          // 顶点坐标数据缓冲
    FloatBuffer mColorBuffer;          // 顶点颜色数据缓冲


    //立方体顶点位置坐标
    private float box[] = {
            // 四个顶点绘制两个三角形组成前面
            -0.5f, -0.5f, 0.5f,
            0.5f, -0.5f, 0.5f,
            -0.5f, 0.5f, 0.5f,
            0.5f, 0.5f, 0.5f,

            //四个顶点绘制两个三角形组成后面
            -0.5f, -0.5f, -0.5f,
            -0.5f, 0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, 0.5f, -0.5f,

            //四个顶点绘制两个三角形组成左面
            -0.5f, -0.5f, 0.5f,
            -0.5f, 0.5f, 0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, 0.5f, -0.5f,

            //四个顶点绘制两个三角形组成右面
            0.5f, -0.5f, -0.5f,
            0.5f, 0.5f, -0.5f,
            0.5f, -0.5f, 0.5f,
            0.5f, 0.5f, 0.5f,

            //四个顶点绘制两个三角形组成上面
            -0.5f, 0.5f, 0.5f,
            0.5f, 0.5f, 0.5f,
            -0.5f, 0.5f, -0.5f,
            0.5f, 0.5f, -0.5f,

            //四个顶点绘制两个三角形组成下面
            -0.5f, -0.5f, 0.5f,
            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, 0.5f,
            0.5f, -0.5f, -0.5f
    };

    //立方体顶点颜色
    private float box2[] = {
            // 前
            1f, 0f, 0f, 1f,
            1f, 0f, 0f, 1f,
            1f, 0f, 0f, 1f,
            1f, 0f, 0f, 1f,

            //后
            1f, 0f, 0.5f, 1f,
            1f, 0f, 0.5f, 1f,
            1f, 0f, 0.5f, 1f,
            1f, 0f, 0.5f, 1f,

            //左
            0f, 1f, 0f, 1f,
            0f, 1f, 0f, 1f,
            0f, 1f, 0f, 1f,
            0f, 1f, 0f, 1f,

            //右
            0f, 1f, 0.5f, 1f,
            0f, 1f, 0.5f, 1f,
            0f, 1f, 0.5f, 1f,
            0f, 1f, 0.5f, 1f,

            //上
            0f, 0f, 1f, 1f,
            0f, 0f, 1f, 1f,
            0f, 0f, 1f, 1f,
            0f, 0f, 1f, 1f,

            //下
            0f, 0f, 0.5f, 1f,
            0f, 0f, 0.5f, 1f,
            0f, 0f, 0.5f, 1f,
            0f, 0f, 0.5f, 1f,
    };

    public MyRenderer() {
        //将顶点坐标float[]数组转换为OpenGL ES所需的FloatBuffer
        mVertexBuffer = floatBufferUtil(box);
        mColorBuffer = floatBufferUtil(box2);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // 关闭抗抖动
        gl.glDisable(GL10.GL_DITHER);
        // 设置系统对透视进行修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
        //设置清屏色
        gl.glClearColor(0.7f, 0.9f, 0.9f, 1.0f);
        // 设置阴影平滑模式
        gl.glShadeModel(GL10.GL_SMOOTH);
        // 启用深度测试
        gl.glEnable(GL10.GL_DEPTH_TEST);
        // 设置深度测试的类型
        gl.glDepthFunc(GL10.GL_LEQUAL);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // 设置3D视窗的大小及位置
        gl.glViewport(0, 0, width, height);
        // 将当前矩阵模式设为投影矩阵
        gl.glMatrixMode(GL10.GL_PROJECTION);
        // 初始化单位矩阵
        gl.glLoadIdentity();
        // 计算透视视窗的宽度、高度比
        float ratio = (float) width / height;
        // 调用此方法设置透视视窗的空间大小。
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }

    // 绘制图形的方法
    @Override
    public void onDrawFrame(GL10 gl) {
        // 清除屏幕缓存和深度缓存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // 启用顶点坐标数据
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        //重置模型矩阵
        gl.glLoadIdentity();
        // 设置当前矩阵模式为模型视图。
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        //设置顶点坐标
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);

        // 对图像进行旋转操作
        gl.glRotatef(280, -0.1f, -0.1f, 0.05f);

        // 下面几个旋转，可以分别看到立方体的每个面。
//        gl.glRotatef(180, 0.0f, 1.0f, 0.0f);//绕y轴旋转180度，看后面
//        gl.glRotatef(90, 0.0f, 1.0f, 0.0f);//绕y轴旋转90度，看左面
//        gl.glRotatef(-90, 0.0f, 1.0f, 0.0f);//绕y轴旋转-90度，看右面
//        gl.glRotatef(90, 1.0f, 0.0f, 0.0f);//绕x轴旋转90度，看上面
//        gl.glRotatef(-90, 1.0f, 0.0f, 0.0f);//绕x轴旋转-90度，看下面


        // 绘制FRONT和BACK两个面
        gl.glColor4f(1, 0, 0, 1);
        //绘制第一个立方体面
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        gl.glColor4f(1, 0, 0.5f, 1);
        //绘制第二个立方体面
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);

        // 绘制LEFT和RIGHT两个面，用绿色渲染
        gl.glColor4f(0, 1, 0, 1);
        //绘制第三个立方体面
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
        gl.glColor4f(0, 1, 0.5f, 1);
        //绘制第四个立方体面
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);

        // 绘制TOP和BOTTOM两个面，用蓝色渲染
        gl.glColor4f(0, 0, 1, 1);
        //绘制第五个立方体面
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
        gl.glColor4f(0, 0, 0.5f, 1);
        //绘制第六个立方体面
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
    }

    // 定义一个工具方法，将float[]数组转换为OpenGL ES所需的FloatBuffer
    private FloatBuffer floatBufferUtil(float[] arr) {
        FloatBuffer mBuffer;
        // 初始化ByteBuffer，长度为arr数组的长度*4，因为一个int占4个字节
        ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
        // 数组排列用nativeOrder
        qbb.order(ByteOrder.nativeOrder());
        mBuffer = qbb.asFloatBuffer();
        mBuffer.put(arr);
        mBuffer.position(0);
        return mBuffer;
    }
}